#ifndef HASHFUCTION_H_INCLUDED
#define HASHFUCTION_H_INCLUDED


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "BFClass.h"

int HashFunctionNum = 0;//控制使用的hash函数个数

void GetHashFunctionNum(int num)
{
   HashFunctionNum = num;
}

int CheckBit(BloomFilter BF, int BitCount)
{
    printf("%d,",BitCount);
    if(BF.dicthash[BitCount] == 1)
        return 1;
    return 0;
}
/***********************************************
	函数名称: bool hash1(char* buffer, unsigned int*& dicthash, int command=0)
	函数功能: 将字符串按照ascii码变为数字，并得到其积，最后对比特长度取余，
               如果int参数为1则将bloomfilter对应标志位置1，否则跳过。之后查询该位置是否为1.
	传入参数: char* buffer--目标字符串，int command=0--查询，=1--更改
	返回值: 如果是1返回true，否则为false。
************************************************/
int hash1(char* buffer,BloomFilter BF, int command)
{
    if(HashFunctionNum < 1)
        return 1;

	unsigned int tmp = 1;
	while (*buffer != '\0')
	{
	    //printf("111");
		tmp *= (int)(*buffer);
		tmp %= BF.BloomFilterBitCount;
		buffer++;
	}
	if (command == 1){
        BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
        return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);

}
/***********************************************
	函数名称: bool hash2(char* buffer, unsigned  int*& dicthash, int command = 0)
	函数功能: 将字符串按照ascii码变为数字，并得到其和，最后对比特长度取余，
               如果int参数为1则将bloomfilter对应标志位置1，否则跳过。之后查询该位置是否为1.
	传入参数: char* buffer--目标字符串，int command=0--查询，=1--更改
	返回值: 如果是1返回true，否则为false。
************************************************/
int hash2(char* buffer, BloomFilter BF, int command )
{
    if(HashFunctionNum < 2)
        return 1;

	unsigned int tmp = 0;
	while (*buffer != '\0')
	{
		tmp += (int)(*buffer);

		buffer++;
	}
	//printf("222");
	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}
/***********************************************
	函数名称: bool hash3(char* buffer, unsigned  int*& dicthash, int command = 0)
	函数功能: 将字符串按照ascii码变为数字，并得到平方根取整的和，最后对比特长度取余，
               如果int参数为1则将bloomfilter对应标志位置1，否则跳过。之后查询该位置是否为1.
	传入参数: char* buffer--目标字符串，int command=0--查询，=1--更改
	返回值: 如果是1返回true，否则为false。
************************************************/
int hash3(char* buffer, BloomFilter BF, int command )
{
	if(HashFunctionNum < 3)
        return 1;

	unsigned int tmp = 1;
	while (*buffer != '\0')
	{
		tmp *= (int)(sqrt((double)*buffer));

		buffer++;
	}
	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}
/***********************************************
	函数名称: bool hash34char* buffer, unsigned  int*& dicthash, int command = 0)
	函数功能: 将字符串按照ascii码变为数字，按+-+-。。。顺序依次加减，最后对比特长度取余，
               如果int参数为1则将bloomfilter对应标志位置1，否则跳过。之后查询该位置是否为1.
	传入参数: char* buffer--目标字符串，int command=0--查询，=1--更改
	返回值: 如果是1返回true，否则为false。
************************************************/
int hash4(char* buffer, BloomFilter BF, int command )
{
    if(HashFunctionNum < 5)
        return 1;

	unsigned int tmp = 0;
	unsigned int sign = 1;
	while (*buffer != '\0')
	{
		tmp += sign*(int)(*buffer);
		sign *= -1;
		buffer++;
	}
	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//BKDR Hash Function
int hash5(char* buffer, BloomFilter BF, int command )
{
    if(HashFunctionNum < 5)
        return 1;

    unsigned int tmp = 0;
    unsigned int sign = 131;

    while(*buffer){
        tmp = tmp *sign + (*buffer++);
    }
    tmp = tmp & 0x7FFFFFFF;

    if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//AP Hash Function
int hash6(char* buffer, BloomFilter BF, int command)
{
    if(HashFunctionNum < 6)
        return 1;

    unsigned int tmp = 0;
    int i;

    for(i = 0; *buffer; i++){
        if ((i & 1) == 0){
			tmp ^= ((tmp << 7) ^ (*buffer++) ^ (tmp >> 3));
		}
		else{
			tmp ^= (~((tmp << 11) ^ (*buffer++) ^ (tmp >> 5)));
		}
    }
    tmp = tmp & 0x7FFFFFFF;

    if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//DJB Hash function
int hash7(char* buffer, BloomFilter BF, int command)
{
    if(HashFunctionNum < 7)
        return 1;

    unsigned int tmp = 5381;

    while (*buffer){
		tmp += (tmp << 5) + (*buffer++);
	}

	tmp = tmp & 0x7FFFFFFF;

	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//JS Hash Function
int hash8(char* buffer, BloomFilter BF, int command)
{
    if(HashFunctionNum < 8)
        return 1;

    unsigned int tmp = 1315423911;

	while (*buffer)
	{
		tmp ^= ((tmp << 5) + (*buffer++) + (tmp >> 2));
	}

	tmp = tmp & 0x7FFFFFFF;

	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//RS Hash Function
int hash9(char* buffer, BloomFilter BF, int command)
{
    if(HashFunctionNum < 9)
        return 1;

    unsigned int tmp = 0;
	unsigned int b = 378551;
	unsigned int a = 63689;

	while (*buffer)
	{
		tmp = tmp * a + (*buffer++);
		a *= b;
	}

	tmp = tmp & 0x7FFFFFFF;

	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//SDBM Hash Function
int hash10(char* buffer, BloomFilter BF, int command)
{
    if(HashFunctionNum < 10)
        return 1;

    unsigned int tmp = 0;

	while (*buffer)
	{
		// equivalent to: hash = 65599*hash + (*str++);
		tmp = (*buffer++) + (tmp << 6) + (tmp << 16) - tmp;
	}

	tmp = tmp & 0x7FFFFFFF;

	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//FNV Hash Function
int hash11(char* buffer, BloomFilter BF, int command)
{
    if(HashFunctionNum < 11)
        return 1;

    unsigned int tmp = 0;

	int fnvprime = 0x811C9DC5;

	while (*buffer) {
		tmp *= fnvprime;
		tmp ^= (int)(*buffer++);
	}

	tmp = tmp & 0x7FFFFFFF;

	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//JAVA string hash function
int hash12(char* buffer, BloomFilter BF, int command)
{
    if(HashFunctionNum < 12)
        return 1;

    unsigned int tmp = 0;

	while (*buffer) {
		tmp = tmp * 31 + (*buffer++);
	}

	tmp = tmp & 0x7FFFFFFF;

	if (command == 1){
         BF.dicthash[tmp%BF.BloomFilterBitCount] = 1;
         return 0;
	}else
        return CheckBit(BF,tmp % BF.BloomFilterBitCount);
}

//²åÈëÔªËØ
void Insert(char* buffer)
{
    hash1(buffer,BF,1);
    hash2(buffer,BF,1);
    hash3(buffer,BF,1);
    hash4(buffer,BF,1);
    hash5(buffer,BF,1);
    hash6(buffer,BF,1);
    hash7(buffer,BF,1);
    hash8(buffer,BF,1);
    hash9(buffer,BF,1);
    hash10(buffer,BF,1);
    hash11(buffer,BF,1);
    hash12(buffer,BF,1);
}

//²éÑ¯ÔªËØ
int Query(char * buffer)
{
    int result_1= hash1(buffer,BF,0);
    int result_2 = hash2(buffer,BF,0);
    int result_3 = hash3(buffer,BF,0);
    int result_4 = hash4(buffer,BF,0);
    int result_5 = hash5(buffer,BF,0);
    int result_6 = hash6(buffer,BF,0);
    int result_7 = hash7(buffer,BF,0);
    int result_8 = hash8(buffer,BF,0);
    int result_9 = hash9(buffer,BF,0);
    int result_10 = hash10(buffer,BF,0);
    int result_11 = hash11(buffer,BF,0);
    int result_12 = hash12(buffer,BF,0);
    if(result_1&&result_2&&result_3&&result_4&&result_5&&result_6&&result_7&&result_8&&result_9&&result_10&&result_11&&result_12)
        printf("Element exists!!\n");
    else
        printf("Element does not exist!\n");
    return 0;

}

void ReadFile_Insert(char * File)
{
    FILE* fp = NULL;
    fp = fopen(File, "r");
    if (fp != NULL)
        printf("YES!!\n");
    else
        printf("NO!!\n");
    char row[1024];
    char *token;
    while (fgets(row, 1024, fp) != NULL){
        //printf("Row: %s", row);
        token = strtok(row, ",");
        printf("Token: %s\n", token);
        Insert(token);
    }
    printf("Element insertion completed!\n");
}

void ReadFile_Query(char * File)
{
    FILE* fp = NULL;
    fp = fopen(File, "r");
    if (fp != NULL)
        printf("YES!!\n");
    else
        printf("NO!!\n");
    char row[1024];
    char *token;
    while (fgets(row, 1024, fp) != NULL){
        //printf("Row: %s", row);
        token = strtok(row, ",");
        printf("Token: %s\n", token);
        Query(token);
    }
    printf("Element query completed!\n");
}

#endif // HASHFUCTION_H_INCLUDED
